<template>
	<!-- 我直接绘制最后一个点，就是一边取点一边绘制，不要存到数组里了 -->
	<view
		class="container"
		:class="[showCanvas === true ? '' : 'hidden-canvas']"
		:style="{
			height,
			display: showCanvas === true ? 'block' : 'none',
		}"
	>
		<view
			class="canvas_container"
			:style="{
				padding,
				height,
			}"
		>
			<!-- #ifdef MP-ALIPAY -->
			<canvas
				id="signCanvas"
				type="2d"
				class="canvas"
				:style="{
					height,
				}"
				:disable-scroll="true"
				@touchstart="handleTouchStart"
				@touchmove="handleTouchMove"
				@touchend="handleTouchEnd"
			></canvas>
			<!-- #endif -->
			<!-- #ifdef MP-WEIXIN -->
			<canvas
				canvas-id="signCanvas"
				id="signCanvas"
				class="canvas"
				:style="{
					height,
				}"
				:disable-scroll="true"
				@touchstart="handleTouchStart"
				@touchmove="handleTouchMove"
				@touchend="handleTouchEnd"
			></canvas>
			<!-- #endif -->
			<!-- #ifndef MP-WEIXIN -->
			<canvas
				canvas-id="signCanvas"
				id="signCanvas"
				type="2d"
				class="canvas"
				:style="{
					height,
				}"
				:disable-scroll="true"
				@touchstart="handleTouchStart"
				@touchmove="handleTouchMove"
				@touchend="handleTouchEnd"
			></canvas>
			<!-- #endif -->
		</view>

		<view class="controls">
			<button @click="undo" :disabled="!canUndo">撤销</button>
			<button @click="redo" :disabled="!canRedo">重做</button>
			<button @click="clearCanvas">清除</button>
			<button @click="saveImage">确定</button>
			<!-- <button @click="exportBase64">导出Base64</button> -->
		</view>
	</view>
</template>

<script>
export default {
	emits: ['onSaveImage'],
	props: {
		height: {
			type: String,
			default: '800rpx',
		},
		// 画布的边距
		padding: {
			type: String,
			default: '0',
		},
		// 是否显示 canvas（用于控制渲染时机）
		showCanvas: {
			type: Boolean,
			default: false,
		},
		// 画布的上下偏移量（只有小程序会端有这个属性）
		offsetCTXTop: {
			type: Number,
			default: 0,
		},
		// 画布的左右偏移量（只有小程序会端有这个属性）
		offsetCTXLeft: {
			type: Number,
			default: 0,
		},
	},
	data() {
		return {
			canvasId: 'signCanvas',
			color: '#000000',
			penWidth: 4,
			widths: [1, 2, 4, 6, 8],
			isDrawing: false,
			lastPoint: null,
			currentLine: null,
			lines: [],
			undoneLines: [],
			ctx: null,
			canvasWidth: 0,
			canvasHeight: 0,
			canvasRect: null, // 给定上下文关联的 Canvas 对象的只读引用。
			dpr: 1,
			timer: null, // 定时器
		};
	},
	computed: {
		canUndo() {
			return this.lines.length > 0;
		},
		canRedo() {
			return this.undoneLines.length > 0;
		},
	},
	mounted() {
		this.initCanvas();
	},
	beforeDestroy() {
		this.clearCanvas();
	},
	methods: {
		initCanvas() {
			const that = this;

			that.dpr = uni.getSystemInfoSync().pixelRatio || 1;
			// #ifdef MP-ALIPAY
			my.createSelectorQuery()
				.select(`#${'signCanvas'}`)
				.node()
				.exec(rect => {
					const canvas = rect[0].node;

					if (rect) {
						that.canvasRect = canvas;
						that.canvasWidth = canvas.width * that.dpr;
						that.canvasHeight = canvas.height * that.dpr;
					}
					that.ctx = canvas.getContext('2d');
				});
			// #endif

			// #ifndef MP-ALIPAY
			uni
				.createSelectorQuery()
				.in(that)
				.select(`#${'signCanvas'}`)
				.boundingClientRect(rect => {
					if (rect) {
						that.canvasRect = rect;
						that.canvasWidth = rect.width * that.dpr;
						that.canvasHeight = rect.height * that.dpr;
					}
					that.ctx = uni.createCanvasContext('signCanvas', that);
				})
				.exec();
			// #endif
		},

		getTouchPoint(e) {
			const touch = e.touches ? e.touches[0] : e;
			let x = null;
			let y = null;
			console.log('touch point111:', touch);
			console.log('touch point222:', this.canvasRect);

			// #ifdef MP-ALIPAY
			x = touch.x - this.$props.offsetCTXLeft * 1;
			y = touch.y - this.$props.offsetCTXTop * 1;
			// #endif

			// #ifndef MP-ALIPAY
			x = touch.x - this.canvasRect.left;
			y = touch.y - this.canvasRect.top;
			// #endif
			return { x, y };
		},

		handleTouchStart(e) {
			this.isDrawing = true;
			this.currentLine = [];
			this.lines.push(this.currentLine);
			this.undoneLines = [];
			this.lastPoint = this.getTouchPoint(e);
		},

		handleTouchMove(e) {
			if (!this.isDrawing) return;
			const point = this.getTouchPoint(e);
			const opt = {
				startX: this.lastPoint.x,
				startY: this.lastPoint.y,
				endX: point.x,
				endY: point.y,
				color: this.color,
				width: this.penWidth,
			};
			this.currentLine.push(opt);
			this.lastPoint = point;
			this.drawLine(opt);
		},

		handleTouchEnd() {
			this.isDrawing = false;
			this.currentLine = null;
			this.drawOnce();
		},

		drawLine(line) {
			console.log('line===', line);
			this.ctx.beginPath();
			this.ctx.moveTo(line.startX, line.startY);
			this.ctx.lineTo(line.endX, line.endY);
			// 设置颜色和宽度
			// #ifdef MP-ALIPAY
			this.ctx.strokeStyle = line.color;
			this.ctx.lineWidth = line.width || 2;
			// #endif
			// #ifndef MP-ALIPAY
			this.ctx.setStrokeStyle(line.color);
			this.ctx.setLineWidth(line.width || 2);
			// #endif
			this.ctx.stroke();

			// #ifndef MP-ALIPAY
			this.ctx.draw(true);
			// #endif
		},
		drawOnce() {
			if (!this.ctx) return;

			this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
			for (const lineGroup of this.lines) {
				for (const line of lineGroup) {
					this.drawLine(line);
				}
			}
			// #ifndef MP-ALIPAY
			this.ctx.draw(true);
			// #endif
		},

		clearCanvas() {
			this.lines = [];
			this.undoneLines = [];
			this.currentLine = null;

			this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
			// #ifndef MP-ALIPAY
			this.ctx.draw(true);
			// #endif
		},

		undo() {
			if (this.lines.length > 0) {
				this.undoneLines.push(this.lines.pop());
				this.drawOnce();
			}
		},

		redo() {
			if (this.undoneLines.length > 0) {
				this.lines.push(this.undoneLines.pop());
				this.drawOnce();
			}
		},

		saveImage() {
			this.drawOnce(); // 确保最新画面已绘制

			// #ifdef MP-ALIPAY
			// 支付宝必须用原生 API + canvas 实例
			uni
				.createSelectorQuery()
				.select('#signCanvas')
				.node()
				.exec(res => {
					const canvas = res[0]?.node;

					my.canvasToTempFilePath({
						canvas, // 必须传 canvas 实例
						fileType: 'png',
						success: res => {
							uni.showToast({ title: '保存成功', icon: 'success' });
							console.log('支付宝图片路径:', res.tempFilePath);
							this.$emit('onSaveImage', res.tempFilePath);
						},
						fail: err => {
							uni.showToast({ title: '保存失败', icon: 'error' });
							console.error('支付宝导出失败:', err);
						},
					});
				});
			// #endif

			// #ifndef MP-ALIPAY
			// 微信等平台使用 uni 封装
			uni.canvasToTempFilePath(
				{
					canvasId: 'signCanvas',
					fileType: 'png',
					success: res => {
						uni.showToast({ title: '保存成功', icon: 'success' });
						console.log('图片路径:', res.tempFilePath);
						this.$emit('onSaveImage', res.tempFilePath);
					},
					fail: err => {
						uni.showToast({ title: '保存失败', icon: 'error' });
						console.error('导出失败:', err);
					},
				},
				this // 微信需要传 this
			);
			// #endif
		},

		exportBase64() {
			this.drawOnce(); // 确保最新画面已绘制

			// #ifdef MP-ALIPAY
			uni
				.createSelectorQuery()
				.select('#signCanvas')
				.node()
				.exec(res => {
					const canvas = res[0]?.node;
					if (!canvas) {
						uni.showToast({ title: 'Canvas 未就绪', icon: 'none' });
						return;
					}

					my.canvasToTempFilePath({
						canvas, // 必须传 canvas 实例
						fileType: 'png',
						success: res => {
							// 使用支付宝的文件管理器读取文件并转为 base64
							if (my.getFileSystemManager) {
								const fs = my.getFileSystemManager();
								fs.readFile({
									filePath: res.tempFilePath,
									encoding: 'base64',
									success: fileRes => {
										const base64Data = 'data:image/png;base64,' + fileRes.data;
										my.setClipboardData({
											data: base64Data,
											success: () => {
												uni.showToast({ title: 'Base64已复制', icon: 'none' });
												console.log(base64Data);
											},
										});
									},
								});
							} else {
								uni.showToast({
									title: '当前平台不支持导出Base64',
									icon: 'none',
								});
							}
						},
						fail: err => {
							uni.showToast({ title: '导出失败', icon: 'error' });
							console.error('支付宝导出Base64失败:', err);
						},
					});
				});
			// #endif

			// #ifndef MP-ALIPAY
			uni.canvasToTempFilePath(
				{
					canvasId: 'signCanvas',
					success: res => {
						if (uni.getFileSystemManager) {
							uni.getFileSystemManager().readFile({
								filePath: res.tempFilePath,
								encoding: 'base64',
								success: fileRes => {
									const base64Data = 'data:image/png;base64,' + fileRes.data;
									uni.setClipboardData({ data: base64Data });
									uni.showToast({ title: 'Base64已复制', icon: 'none' });
									console.log(base64Data);
								},
							});
						} else {
							uni.showToast({
								title: '当前平台不支持导出Base64',
								icon: 'none',
							});
						}
					},
					fail: err => {
						console.error('导出Base64失败', err);
					},
				},
				this // 微信需要传 this
			);
			// #endif
		},
	},
};
</script>

<style scoped>
.container {
	width: 100%;
	position: relative;
}

.canvas_container {
	width: 100%;
}

.canvas {
	width: 100%;
	background: #fff;
	border: 1px solid #ddd;
}

/* 隐藏 canvas，但保留其渲染能力 */
.hidden-canvas {
	position: absolute;
	top: -9999px;
	left: -9999px;
	opacity: 0;
}

.controls {
	margin-top: 10px;
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	align-items: center;
}

.color-picker {
	width: 40px;
	height: 40px;
	border: none;
	cursor: pointer;
}

.width-control button {
	margin-right: 6px;
	padding: 4px 8px;
	border: 1px solid #ccc;
	background: white;
	cursor: pointer;
	outline: none;
}
.width-control button.active {
	border-color: #007aff;
	color: #007aff;
}

button:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}
</style>
